#include "fxcc/mono/Behivor.h"

using namespace mono;

bool Behivor::Init()
{
    if (m_Path.empty())
    {
        return false;
    }
    if (!fs::exists(m_Path))
    {
        ztclog::info("mono dll no exist [%s]", m_Path.c_str());
        return false;
    }

    assembly = mono_domain_assembly_open(mono_domain_get(), m_Path.c_str());
    if (!assembly)
    {
        ztclog::info("Failed to load assembly ");
        return false;
    }

    image = mono_assembly_get_image(assembly);

    if (!image)
    {
        ztclog::info("failed to load image");
        return false;
    }

    const MonoTableInfo *type_table = mono_image_get_table_info(image, MONO_TABLE_TYPEDEF);
    if (!type_table)
    {
        ztclog::info("Failed to get type definition table!");
        return false;
    }

    int rows = mono_table_info_get_rows(type_table);
    for (int i = 0; i < rows; ++i)
    {
        uint32_t cols[MONO_TYPEDEF_SIZE];
        mono_metadata_decode_row(type_table, i, cols, MONO_TYPEDEF_SIZE);

        const char *class_name = mono_metadata_string_heap(image, cols[MONO_TYPEDEF_NAME]);
        const char *namespace_name = mono_metadata_string_heap(image, cols[MONO_TYPEDEF_NAMESPACE]);

        LoadClazz(namespace_name, class_name);
    }
    return true;
};

bool Behivor::LoadClazz(const std::string &nmsp, const std::string &name)
{

    Clazz::Desc desc;
    desc.image = image;
    desc.m_Name = name;
    desc.m_Namespace = nmsp;

    auto inst = std::make_shared<Clazz>(desc);

    if (inst->m_Available)
    {
        m_Clazzs[desc] = inst;
    }
    else
    {
        ztclog::info("failed load clazz from desc");
    }
    return inst->m_Available;
};

std::shared_ptr<Clazz> Behivor::GetClazz(const std::string &nmsp, const std::string &name)
{
    Clazz::Desc desc;
    desc.m_Name = name;
    desc.m_Namespace = nmsp;
    if (m_Clazzs.find(desc) == m_Clazzs.end())
    {
        ztclog::info("failed find clazz");
        return 0;
    }
    return m_Clazzs[desc];
};